﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace BoYuan.Framework.Uitility.Extensions
{
    public static class DataTableExtensions
    {
        /// <summary>
        /// Linq匿名对象集合转成DataTable
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="query">The query.</param>
        /// <returns></returns>
        public static DataTable ToDataTable<T>(this IEnumerable<T> query)
        {
            DataTable tbl = new DataTable();
            PropertyInfo[] props = null;
            foreach (T item in query)
            {
                if (props == null) //尚未初始化
                {
                    Type t = item.GetType();
                    props = t.GetProperties();
                    foreach (PropertyInfo pi in props)
                    {
                        Type colType = pi.PropertyType;
                        //針對Nullable<>特別處理
                        if (colType.IsGenericType
                            && colType.GetGenericTypeDefinition() == typeof(Nullable<>))
                            colType = colType.GetGenericArguments()[0];
                        //建立欄位
                        tbl.Columns.Add(pi.Name, colType);
                    }
                }
                DataRow row = tbl.NewRow();
                foreach (PropertyInfo pi in props)
                    row[pi.Name] = pi.GetValue(item, null) ?? DBNull.Value;
                tbl.Rows.Add(row);
            }
            return tbl;
        }

        /// <summary> 
        /// 将ObjectList转化一个DataTable 
        /// </summary> 
        /// <typeparam name="T"></typeparam> 
        /// <param name="list"></param> 
        /// <returns></returns> 
        public static DataTable ToDataTable<T>(this IEnumerable<T> list, params string[] tableName)
        {
            string str = "1,2,3,4,5,6";
            string[] strList = str.Split(',');//按逗号分组 ，
            //如果你想取值4，也就是索引3（因为索引是从0开始的）
            string fourStr = strList[3];


            //创建属性的集合 
            List<PropertyInfo> pList = new List<PropertyInfo>();
            //获得反射的入口 
            Type type = typeof(T);
            string tname = "Table1";
            if (tableName != null && tableName.Length >= 1)
            {
                tname = tableName[0];
            }
            DataTable dt = new DataTable(tname);
            //把所有的public属性加入到集合 并添加DataTable的列 
            Array.ForEach<PropertyInfo>(type.GetProperties(), p =>
            {
                pList.Add(p);
                var theType = p.PropertyType;
                //处理可空类型
                if (theType.IsGenericType && theType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
                {
                    dt.Columns.Add(p.Name, Nullable.GetUnderlyingType(theType));
                }
                else
                {
                    dt.Columns.Add(p.Name, theType);
                }
            });

            if (list != null)
            {
                foreach (var item in list)
                {
                    //创建一个DataRow实例 
                    DataRow row = dt.NewRow();
                    //给row 赋值 
                    pList.ForEach(p =>
                    {
                        var v = p.GetValue(item, null);
                        row[p.Name] = v == null ? DBNull.Value : v;
                    });
                    //加入到DataTable 
                    dt.Rows.Add(row);
                }
            }
            return dt;
        }

        /// <summary>
        /// DataTable转List
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static IList<T> DtToList<T>(this DataTable dt) where T : new()
        {
            // 定义集合    
            IList<T> ts = new List<T>();

            // 获得此模型的类型   
            Type type = typeof(T);
            string tempName = "";

            foreach (DataRow dr in dt.Rows)
            {
                T t = new T();
                // 获得此模型的公共属性      
                PropertyInfo[] propertys = t.GetType().GetProperties();
                foreach (PropertyInfo pi in propertys)
                {
                    tempName = pi.Name;  // 检查DataTable是否包含此列    

                    if (dt.Columns.Contains(tempName))
                    {
                        // 判断此属性是否有Setter      
                        if (!pi.CanWrite) continue;

                        object value = dr[tempName];
                        if (value != DBNull.Value)
                            pi.SetValue(t, value, null);
                    }
                }
                ts.Add(t);
            }
            return ts;
        }

        
    }
}

